#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using UTable.Input;
using UTable.Objects.Controls;

namespace UTable.Objects
{

    /// <summary>
    /// The tree that consists of all UObject entities
    /// The implementation of the interfaces is just redirecting the request to the corresponding UObject entity
    /// </summary>
    public class UObjectTreeHost : IObjectTree
    {
        #region Private Members

        private UObjectEntity _treeRoot;
        private UCanvas _hostElement = new UCanvas();
        
        #endregion

        #region Static Members

        private static UObjectTreeHost _instance = new UObjectTreeHost();
        public static readonly bool CONTENT_INITIAL_FIRST = false;

        #endregion

        #region IObjectTree Members

        void _hostElement_Loaded(object sender, RoutedEventArgs e)
        {
            (TreeRoot as IObject).Width = this.TreeWidth;
            (TreeRoot as IObject).Height = this.TreeHeight;
        }

        public void SetRoot(IObject root)
        {
            _treeRoot = root as UObjectEntity;
            if (_treeRoot != null)
            {
                _hostElement.Children.Clear();
                _hostElement.Children.Add(_treeRoot);
                _hostElement.Loaded += new RoutedEventHandler(_hostElement_Loaded);
            }
        }

        public FrameworkElement HostElement
        {
            get
            {
                return _hostElement;
            }
        }

        public void RegisterVisualTree(IInputManager inputManager)
        {
            UTableHelper.RegisterVisualTree(this);
            UTableHelper.RegisterInputManager(inputManager);
        }

        #endregion

        #region IVisualTree Members

        public IVisualNode TreeRoot
        {
            get
            {
                return _treeRoot;
            }
        }

        public double TreeWidth
        {
            get { return HostElement.ActualWidth; }
        }

        public double TreeHeight
        {
            get { return HostElement.ActualHeight; }
        }

        #region Public Methods

        public T FindObjectParent<T>(DependencyObject o) where T : DependencyObject
        {
            DependencyObject target = o;
            do 
            {
                target = VisualTreeHelper.GetParent(target);
            } while (target != null && !(target is T));
            return target as T;
        }

        #endregion

        public IVisualNode GetNodeByID(String id)
        {
            if (TreeRoot is IObjectEntity)
                return (TreeRoot as IObjectEntity).GetObjectByID(id);
            return null;
        }

        public IVisualNode GetParent(IVisualNode obj)
        {
            if (obj is UObjectEntity)
            {
                return (obj as UObjectEntity).Owner;
            }
            else
            {
                return null;
            }
        }

        public IVisualNode GetChild(IVisualNode obj, int index)
        {
            if (obj is UObjectEntity && GetChildrenCount(obj) > index)
            {
                return (obj as UObjectEntity).Children[index];
            }
            else
                return null;
        }

        public int GetChildrenCount(IVisualNode obj)
        {
            if (obj is UObjectEntity)
            {
                return (obj as UObjectEntity).Children.Count;
            }
            else
                return 0;
        }

        public HitTestResult HitTest(HitTestParameters hitTestParameters)
        {
            if (_treeRoot == null)
                return null;
            else
                return _treeRoot.HitTest(hitTestParameters);
        }

        public Point TranslatePoint(Point point, IVisualNode relativeTo)
        {
            if (!(relativeTo is IObjectEntity))
            {
                return new Point(double.NaN, double.NaN);
            }
            FrameworkElement r = relativeTo as FrameworkElement;
            if (r == null)
                return new Point(double.NaN, double.NaN);
            return this.HostElement.TranslatePoint(point, r);
        }

        public Point TranslatePoint(IVisualNode node, Point point, IVisualNode relativeTo)
        {
            if (!(node is IObjectEntity) || ! (relativeTo is IObjectEntity))
                return new Point(double.NaN, double.NaN);
            IObjectEntity obj = node as IObjectEntity;
            return obj.TranslatePoint(point, relativeTo);
        }

        #endregion

        private UObjectTreeHost()
        {
        }

        public static UObjectTreeHost GetInstance()
        {
            return _instance;
        }
    }
}
